/**
 * Create in 2012-4-18.
 */
package kit4j.view.cs.awt;

import java.awt.Component;
import java.awt.Dimension;
import java.lang.reflect.InvocationTargetException;

/**
 * 组件分步伸缩操作实现类。
 * 
 * @author MiniKnife
 * 
 */
public class DynamicComponentStepStretcher extends AbstractDynamicComponentStepOperator {

	/**
	 * 绑定的需要伸缩的组件对象。
	 */
	private Component component;

	/**
	 * 当前伸缩的尺寸。
	 */
	private Dimension currentSize;

	/**
	 * 下一个将要伸缩到的尺寸。
	 */
	private Dimension nextSize;

	/**
	 * 组件对象伸缩的初始尺寸。
	 */
	private Dimension initialSize;
	
	/**
	 * 组件对象伸缩的目标尺寸。
	 */
	private Dimension targetSize;

	/**
	 * 伸缩过程中的尺寸增量。
	 */
	private Dimension sizeIncrement;

	/**
	 * 创建一个组件伸缩操作者对象。
	 * 
	 * @param component
	 *            要伸缩的组件对象
	 * @param initialSize
	 *            组件对象伸缩的初始尺寸
	 * @param targetSize
	 *            组件对象要伸缩到的目标尺寸
	 * @param sizeIncrement
	 *            伸缩过程中的尺寸增量
	 * @throws IllegalArgumentException
	 *             如果{@code sizeIncrement.width}和{@code sizeIncrement.height}都为0，则抛出此异常。
	 */
	public DynamicComponentStepStretcher(Component component, Dimension initialSize, Dimension targetSize,
			Dimension sizeIncrement) throws IllegalArgumentException {
		super(Math.abs(targetSize.width - initialSize.width) + Math.abs(targetSize.height - initialSize.height));

		checkSizeParameters(initialSize, targetSize, sizeIncrement);

		this.component = component;
		this.nextSize = cloneDimension(initialSize);
		this.currentSize = cloneDimension(initialSize);
		this.initialSize = cloneDimension(initialSize);
		this.targetSize = cloneDimension(targetSize);
		this.sizeIncrement = cloneDimension(sizeIncrement);
	}

	/**
	 * 验证尺寸增量是否合法。
	 * 
	 * @param sizeIncrement
	 *            伸缩过程中的尺寸增量
	 * @throws IllegalArgumentException
	 *             如果{@code sizeIncrement.width}和{@code sizeIncrement.height}都为0，则抛出此异常。
	 */
	private void checkSizeParameters(Dimension initialSize, Dimension targetSize, Dimension sizeIncrement) throws IllegalArgumentException {
		if (sizeIncrement.width == 0 && sizeIncrement.height == 0) {
			throw new IllegalArgumentException("sizeIncrement.width=0, sizeIncrement.height = 0");
		} else if (sizeIncrement.width == 0 && initialSize.width != targetSize.width) {
			throw new IllegalArgumentException("initialSize.width!=targetSize.width, sizeIncrement.width=0");
		} else if (sizeIncrement.width > 0 && initialSize.width > targetSize.width) {
			throw new IllegalArgumentException("initialSize.width>targetSize.width, sizeIncrement.width>0");
		} else if (sizeIncrement.width < 0 && initialSize.width < targetSize.width) {
			throw new IllegalArgumentException("initialSize.width<targetSize.width, sizeIncrement.width<0");
		}
	}

	/**
	 * 创建一个指定Dimension对象的副本。
	 * 
	 * @param dimension
	 *            要复制的Dimension对象
	 * @return 复制创建的Dimension对象
	 */
	private Dimension cloneDimension(Dimension dimension) {
		return new Dimension(dimension.width, dimension.height);
	}

	/**
	 * @see kit4j.common.task.StepTask.StepTaskCallback#execute()
	 */
	@Override
	public void execute() {
		try {
			invokeAndWait(new Runnable() {

				@Override
				public void run() {
					component.setSize(nextSize);

					currentSize.setSize(nextSize);
					nextSize.setSize(nextSize.width + sizeIncrement.width, nextSize.height + sizeIncrement.height);
					
					if(initialSize.width > targetSize.width && nextSize.width < targetSize.width || 
							initialSize.width < targetSize.width && nextSize.width > targetSize.width) {
						nextSize.setSize(targetSize.width, nextSize.height);
					}
					if(initialSize.height > targetSize.height && nextSize.height < targetSize.height || 
							initialSize.height < targetSize.height && nextSize.height > targetSize.height) {
						nextSize.setSize(nextSize.width, targetSize.height);
					}
				}

			});
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	/**
	 * @see kit4j.common.task.StepTask.StepTaskCallback#getCurrentTaskProgressRate()
	 */
	@Override
	public long getCurrentTaskProgressRate() {
		return Math.abs(currentSize.width - initialSize.width) + Math.abs(currentSize.height - initialSize.height);
	}

}
